/**
 * @author brianxia
 * @version 1.0
 * @date 2021/10/7 18:42
 */
public class ThreadStatus {

    /**
     * 新建
     * 当一个线程对象被创建，但还未调用 start 方法时处于新建状态
     * 此时未与操作系统底层线程关联
     */

    public static void NEW(){
        Thread thread = new Thread();
        System.out.println(thread.getState());
    }

    /**
     * 可运行
     * 调用了 start 方法，就会由新建进入可运行
     * 此时与底层线程关联，由操作系统调度执行
     */
    public static void RUNNABLE(){
        Thread thread = new Thread(() -> {
            while (true){

            }
        });
        thread.start();
        System.out.println(thread.getState());
    }

    /**
     * 终结
     * 线程内代码已经执行完毕，由可运行进入终结
     * 此时会取消与底层线程关联
     */
    public static void TERMINATED() throws InterruptedException {
        Thread thread = new Thread();
        thread.start();
        Thread.sleep(100L);
        System.out.println(thread.getState());
    }

    /**
     * 阻塞
     * 当获取锁失败后，由可运行进入 Monitor 的阻塞队列阻塞，此时不占用 cpu 时间
     * 当持锁线程释放锁时，会按照一定规则唤醒阻塞队列中的阻塞线程，唤醒后的线程进入可运行状态
     * @throws InterruptedException
     */

    public static void BLOCKED() throws InterruptedException {
        Object o = new Object();
        Thread thread1 = new Thread(() -> {
            synchronized (o){
                try {
                    Thread.sleep(1000L);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        Thread thread2 = new Thread(() -> {
            synchronized (o){
                try {
                    Thread.sleep(1000L);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        thread1.start();
        Thread.sleep(100L);
        thread2.start();
        Thread.sleep(100L);
        System.out.println(thread2.getState());

        Thread.sleep(2000L);
        System.out.println(thread2.getState());
    }

    /**
     * 等待
     * 当获取锁成功后，但由于条件不满足，调用了 wait() 方法，此时从可运行状态释放锁进入 Monitor 等待集合等待，同样不占用 cpu 时间
     * 当其它持锁线程调用 notify() 或 notifyAll() 方法，会按照一定规则唤醒等待集合中的等待线程，恢复为可运行状态
     */

    public static void WAITING() throws InterruptedException {
        Object o = new Object();
        Thread thread1 = new Thread(() -> {
            synchronized (o){
                try {
                    o.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        });
        thread1.start();
        Thread.sleep(100L);
        synchronized (o){
            System.out.println(thread1.getState());
            o.notify();
        }

    }

    /**
     * 有时限等待
     * 当获取锁成功后，但由于条件不满足，调用了 wait(long) 方法，此时从可运行状态释放锁进入 Monitor 等待集合进行有时限等待，同样不占用 cpu 时间
     * 当其它持锁线程调用 notify() 或 notifyAll() 方法，会按照一定规则唤醒等待集合中的有时限等待线程，恢复为可运行状态，并重新去竞争锁
     * 如果等待超时，也会从有时限等待状态恢复为可运行状态，并重新去竞争锁
     * 还有一种情况是调用 sleep(long) 方法也会从可运行状态进入有时限等待状态，但与 Monitor 无关，不需要主动唤醒，超时时间到自然恢复为可运行状态
     * @throws InterruptedException
     */
    public static void TIMED_WAITING() throws InterruptedException {
        int a = 5;
        Object o = new Object();
        Thread thread1 = new Thread(() -> {
            try {
                Thread.sleep(1000L);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        thread1.start();
        Thread.sleep(100L);
        System.out.println(thread1.getState());
    }

    public static void main(String[] args) throws InterruptedException {
        //NEW();
        //RUNNABLE();
        //TERMINATED();
        //BLOCKED();
        //WAITING();
        TIMED_WAITING();
    }
}
